﻿using DVM.DV.Model;
using System.Reflection;

namespace DVM.DV.Extensions
{
    public class CommmonFieldExtend
    {

        public static CommmonFieldExtend GetStatic()
        {
            return new CommmonFieldExtend();
        }

        /// <summary>
        /// 过滤得到需要查询的字段
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="lists"></param>
        public InitInfo InitFilterFields<TSource, TResult>(List<TSource> lists, List<TResult> rLists)
            where TSource : class
             where TResult : class
        {
            #region 查询输入属性基础信息
            var Init = new InitInfo();
            Init.SourceName = typeof(TSource).Name;
            Init.SourceType = typeof(TSource);
            Dictionary<string, FieldPropertyInfo> fieldPropertyDic = GetPropertyInfo(lists);
            Init.SourcePropertyInfos = fieldPropertyDic;
            #endregion

            #region 查询输入属性基础信息
            Init.OutPutName = typeof(TResult).Name;
            Init.OutPutType = typeof(TResult);
            Init.OutPutPropertyInfos = GetOutPutPropertyInfo(rLists); ;
            #endregion
            return Init;
        }

        private static Dictionary<string, FieldPropertyInfo> GetPropertyInfo<T>(List<T> lists)
            where T : class
        {
            var fieldPropertyDic = new Dictionary<string, FieldPropertyInfo>();
            var properties = typeof(T).GetProperties();
            foreach (var property in properties)
            {
                var jsonPropertys = property.GetCustomAttribute(typeof(PropertySetAttribute));
                if (jsonPropertys == null)
                    continue;
                var attr = jsonPropertys as PropertySetAttribute;
                var propertyName = attr?.SetPropertyName;
                if (string.IsNullOrEmpty(propertyName))
                    continue;
                Type propertyType = property.PropertyType;
                if (!propertyType.IsValueType)
                    continue;
                var fields = DBField.GetStatic().ConstValues;
                if (fields.Contains(propertyName))
                {
                    var fieldPropertyInfo = new FieldPropertyInfo
                    {
                        PropertySetName = propertyName,
                        FieldType = propertyType,
                        FieldValue = GetPropertyValueList(lists, property.Name)
                    };
                    fieldPropertyDic[property.Name] = fieldPropertyInfo;
                }
            }
            return fieldPropertyDic;
        }

        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="lists"></param>
        /// <returns></returns>
        private static Dictionary<string, FieldPropertyInfo> GetOutPutPropertyInfo<T>(List<T> lists)
          where T : class
        {
            var fieldPropertyDic = new Dictionary<string, FieldPropertyInfo>();
            var properties = typeof(T).GetProperties();
            foreach (var property in properties)
            {
                var jsonPropertys = property.GetCustomAttribute(typeof(PropertySetAttribute));
                if (jsonPropertys == null)
                    continue;
                var attr = jsonPropertys as PropertySetAttribute;
                var propertyName = attr?.SetPropertyName;
                if (string.IsNullOrEmpty(propertyName))
                    continue;
                Type propertyType = property.PropertyType;
                var fields = DBField.GetStatic().ConstValues;
                if (!fields.Contains(propertyName)) continue;
                var fieldPropertyInfo = new FieldPropertyInfo
                {
                    PropertySetName = propertyName,
                    FieldType = propertyType,
                    FieldValue = GetPropertyValueList(lists, property.Name)
                };
                fieldPropertyDic[property.Name] = fieldPropertyInfo;
            }
            return fieldPropertyDic;
        }

        /// <summary>
        ///  获取 List<T> 中 T 类型的某个属性的值集合的方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        private static List<object> GetPropertyValueList<T>(List<T> list, string propertyName)
        {
            PropertyInfo property = typeof(T).GetProperty(propertyName);
            if (property == null)
            {
                return null;
            }
            return list.Select(item => property.GetValue(item)).ToList();
        }
    }
}
